/*! \file constanttable.g
	\author HiddenSeeker

	This file describes a constant table and other related stuff, like common used java constants in this project
 */

#include<string>
#include<vector>
#include<map>
#include"attrinfo.h"
#pragma once


/*! A file, where constant table can be placed
 */
class JBFile;

/*! Used constant entry
 */
class ConstantEntry
{
private:
		unsigned char m_tag;
protected:
		/*! Tests, whether two pool entry is equal
			\param[in] entry used entry
		 */
		virtual bool isEqual(ConstantEntry * entry)=0;
		/*! Used to write constant to jbfile
			\param[in] file used file
		 */
		virtual void writeData(JBFile * file)=0;
public:
		/*! Common constructor of all constants
		 */
		inline ConstantEntry(unsigned char tag)
		{
			m_tag=tag;
		}
		/*! If constant entry is equal returns true
			\param[in] entry used entry
		 */
		bool equal(ConstantEntry * entry);
		/*! Writes a constant to java bytecode
			\param[in] file used file
		 */
		void write(JBFile * file);
		/*! Prints a  constant entry
		 */
		virtual void print()=0;
		/*! Destructs a constant entry, does nothing currently
		 */
		virtual ~ConstantEntry();
};

/*! A UTF8 constant
 */
class C_UTF8: public ConstantEntry
{
  private:
			std::string m_str;
  protected:
			virtual bool isEqual(ConstantEntry * entry);
			virtual void writeData(JBFile * file);
  public:
	  /*! Prints a  constant entry
	   */
	  virtual void print();
	  inline C_UTF8(const std::string & s) : ConstantEntry(1)
	  {
		m_str=s;
	  }
};

/*! A String constant
 */
class C_STRING: public ConstantEntry
{
 private:
		  unsigned short m_ind;
 protected:
			virtual bool isEqual(ConstantEntry * entry);
			virtual void writeData(JBFile * file);
 public:
	     inline C_STRING(unsigned short index) : ConstantEntry(8)
		 {
				m_ind=index;
		 }
	     /*! Prints a  constant entry
		  */
		 virtual void print();
};

/*! A  Float constant
 */
class C_FLOAT: public ConstantEntry
{
 private:
		 float m_f;
 protected:
			virtual bool isEqual(ConstantEntry * entry);
			virtual void writeData(JBFile * file);
 public:
	     inline C_FLOAT(float f) : ConstantEntry(4)
		 {
				m_f=f;
		 }
		 /*! Prints a  constant entry
		  */
		 virtual void print();
};

class C_INTEGER: public ConstantEntry
{
 private:	
		  int m_d;
 protected:
			virtual bool isEqual(ConstantEntry * entry);
			virtual void writeData(JBFile * file);
 public:
	 inline C_INTEGER(int d) : ConstantEntry(3)
	 {
		 m_d=d;
	 }
	 /*! Prints a  constant entry
	  */
     virtual void print();
};

class C_CLASS: public ConstantEntry
{
 private:
		  unsigned short m_ind;
 protected:
			virtual bool isEqual(ConstantEntry * entry);
			virtual void writeData(JBFile * file);
 public:
	      inline C_CLASS(unsigned short index) : ConstantEntry(7)
		  {
				m_ind=index;
		  }
		  /*! Prints a  constant entry
		   */
		  virtual void print();
};

class C_NAMEANDTYPE: public ConstantEntry
{
 private:
		 unsigned short  m_name;
		 unsigned short  m_descriptor;
 protected:
		 virtual bool isEqual(ConstantEntry * entry);
		 virtual void writeData(JBFile * file);
 public:
		inline C_NAMEANDTYPE(unsigned short name,unsigned short dsc) : ConstantEntry(12)
		{
				m_name=name;
				m_descriptor=dsc;
		}
		/*! Prints a  constant entry
		 */
		virtual void print();
};

class C_ATTRIBUTEREF: public ConstantEntry
{
 private:
		 unsigned short m_class;
		 unsigned short m_name_and_type;
 protected:
		 virtual bool isEqual(ConstantEntry * entry);
		 virtual void writeData(JBFile * file);
		 /*! Prints a tag
		  */
		 virtual void printTag()=0;
 public:
		inline C_ATTRIBUTEREF(unsigned short _class,unsigned short nat, int tag) : ConstantEntry(tag)
		{
				m_class=_class;
				m_name_and_type=nat;
		}
		/*! Prints a  constant entry
		 */
		virtual void print();
};

class C_FIELDREF: public C_ATTRIBUTEREF
{
 protected:
		/*! Prints a tag
		 */
		virtual void printTag();
 public:
	   inline C_FIELDREF(unsigned short _class,unsigned short nat) : C_ATTRIBUTEREF(_class,nat,9)
	   {
				
	   }
};

class C_METHODREF: public C_ATTRIBUTEREF
{
 protected:
		/*! Prints a tag
		 */
		virtual void printTag();
 public:
	   inline C_METHODREF(unsigned short _class,unsigned short nat) : C_ATTRIBUTEREF(_class,nat,10)
	   {
				
	   }
};

//Interface method ref
class C_IMETHODREF: public C_ATTRIBUTEREF
{
 protected:
		/*! Prints a tag
		 */
		virtual void printTag();
 public:
	   inline C_IMETHODREF(unsigned short _class,unsigned short nat) : C_ATTRIBUTEREF(_class,nat,11)
	   {
				
	   }
};



/*! A constant table, that holds all used constants by class. It's a common used table

	For character we don't create constants, just use bipush to add it to stack with code index

	For boolean we don't create constants, just use iconst_1 if true or iconst_0 if false

 */ 
class ConstantTable
{
 private:
		 std::vector<ConstantEntry *> m_pool;

		 unsigned short addConstant(ConstantEntry * data);
 public:
		 /*! Constant table
		  */
		 ConstantTable();	
		
		 void write(JBFile * file);
		 unsigned short createUTF8(const std::string & l);
		 unsigned short createStringLiteral(const std::string & l);
		 unsigned short createFloat(float f);
     	 unsigned short createInteger(int d);
		 unsigned short createClass(const std::string & s);
		 /*! Creates name and type
			 \param[in] n name
			 \param[on] d descriptor
		  */
		 unsigned short createNameAndType(const std::string & n, const std::string & d);
		 
		 unsigned short createFieldRef(const std::string & _class, const std::string & name, const std::string &d);
		 unsigned short createMethodRef(const std::string & _class, const std::string & name, const std::string &d);
		 unsigned short createIMethodRef(const std::string & _class, const std::string & name, const std::string &d);
		 
		 unsigned short createMainConvertToArray();

		 unsigned short createConstructorRef( const std::string & parentClass);

		 unsigned short createGetBoolean();

		 unsigned short createBooleanConstructor();
		 unsigned short createIntegerConstructor();
		 unsigned short createRealConstructor();
		 unsigned short createCharacterConstructor();
		 unsigned short createStringConstructor();

		 unsigned short createBooleanClone();
		 unsigned short createIntegerClone();
		 unsigned short createRealClone();
		 unsigned short createCharacterClone();
		 unsigned short createStringClone();


		 unsigned short createRefsEq();
		 unsigned short createRefsNeq();

		 /*! Creates an array constructor ref. Used by ManifestArray to produce arrays
		  */
		 unsigned short createArrayConstructor();
		 /*! Creates array class. Used by ManifestArray to produce arrays
		  */
		 unsigned short createArrayClass();
		 /*! Creates an array make method ref. Used by ManifestArray to create array
		  */
		 unsigned short createArrayMake();
		 /*! Creates array put method ref. Used by ManifestArray to put values to array
		  */
		 unsigned short createArrayPut();
		 /*! Prints a table
		  */
		 void print();
		 AttrInfo createConstructor();
		 AttrInfo createMainDefinition();
		 /*! Can  be used for creation of various definitions, like fields, arrays, or other
		  */
		 AttrInfo createDefinition(const std::string & name, const std::string & dsc);
		 /*! Frees a pool
		  */
		 ~ConstantTable();
};